package text

import (
	"strconv"
	"strings"
	"time"

	"github.com/mitchellh/mapstructure"
)

type textValue struct {
	data []byte
}

func (t *textValue) Bool(def ...bool) bool {
	b, err := j.Json.Bool()
	if err == nil {
		return b
	}

	str, ok := j.Interface().(string)
	if !ok {
		if len(def) == 0 {
			return false
		}
		return def[0]
	}

	b, err = strconv.ParseBool(str)
	if err != nil {
		if len(def) == 0 {
			return false
		}
		return def[0]
	}

	return b
}

func (t *textValue) Int(def ...int) int {
	i, err := j.Json.Int()
	if err == nil {
		return i
	}

	str, ok := j.Interface().(string)
	if !ok {
		if len(def) == 0 {
			return 0
		}
		return def[0]
	}

	i, err = strconv.Atoi(str)
	if err != nil {
		if len(def) == 0 {
			return 0
		}
		return def[0]
	}

	return i
}

func (t *textValue) String(def ...string) string {
	return j.Json.MustString(def...)
}

func (t *textValue) Float64(def ...float64) float64 {
	f, err := j.Json.Float64()
	if err == nil {
		return f
	}

	str, ok := j.Interface().(string)
	if !ok {
		if len(def) == 0 {
			return 0
		}
		return def[0]
	}

	f, err = strconv.ParseFloat(str, 64)
	if err != nil {
		if len(def) == 0 {
			return 0
		}
		return def[0]
	}

	return f
}

func (t *textValue) Duration(def ...time.Duration) time.Duration {
	v, err := j.Json.String()
	if err != nil {
		if len(def) == 0 {
			return 0
		}
		return def[0]
	}

	value, err := time.ParseDuration(v)
	if err != nil {
		if len(def) == 0 {
			return 0
		}
		return def[0]
	}

	return value
}

func (t *textValue) StringSlice(def ...string) []string {
	v, err := j.Json.String()
	if err == nil {
		sl := strings.Split(v, ",")
		if len(sl) > 1 {
			return sl
		}
	}
	return j.Json.MustStringArray(def)
}

func (t *textValue) StringMap(def ...map[string]string) map[string]string {
	res := map[string]string{}
	m, err := j.Json.Map()
	if err != nil {
		if len(def) == 0 {
			return res
		}
		return def[0]
	}

	for k, v := range m {
		res[k] = fmt.Sprintf("%v", v)
	}

	return res
}

func (t *textValue) Scan(v interface{}) error {
	if j.Interface() == nil {
		return nil
	}
	b, err := j.Json.Map()
	if err != nil {
		return err
	}
	config := mapstructure.DecoderConfig{
		DecodeHook: mapstructure.StringToTimeDurationHookFunc(),
		Result:     v,
	}
	decoder, err := mapstructure.NewDecoder(&config)
	if err != nil {
		return err
	}
	return decoder.Decode(b)
}

func (t *textValue) Bytes() []byte {
	b, err := j.Json.Bytes()
	if err != nil {
		// try return marshalled
		b, err = j.Json.MarshalJSON()
		if err != nil {
			return []byte{}
		}
		return b
	}
	return b
}
